package com.msblearn.C_004;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * Atomic Synchronized LongAdder三者比较。
 * 当线程数非常高的是：LongAdder的效率比较高。他使用的是分段锁的概念。也同样是CAS操作。
 * Atomic比Synchronized快。主要是Atomic是使用CAS乐观锁，自旋，无需从用户态转为内核态。
 */
public class T002_Atomic_sync_Longadder {
    static long count1 = 0L;
    static AtomicLong count2 = new AtomicLong(0L);
    static LongAdder count3 = new LongAdder();

    public static void testSync(Thread[] threads) {
        Object lock = new Object();
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int k = 0; k < 1000000; k++) {
                    synchronized (lock) {
                        count1++;
                    }
                }
            });
        }
    }

    public static void testAtomic(Thread[] threads) {
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int k = 0; k < 1000000; k++) {
                    count2.incrementAndGet();
                }
            });
        }
    }

    public static void testLongAdder(Thread[] threads) {
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int k = 0; k < 1000000; k++) {
                    count3.increment();
                }
            });
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[1000];
        long start = System.currentTimeMillis();
        testAtomic(threads);
        for (Thread tt : threads) {
            tt.start();
        }
        for (Thread tt : threads) {
            tt.join();
        }
        long end = System.currentTimeMillis();
        System.out.println("Atomic: " + count2.get() + "   time: " + (end - start));
        //------------------------------
        start = System.currentTimeMillis();
        testSync(threads);
        for (Thread tt : threads) {
            tt.start();
        }
        for (Thread tt : threads) {
            tt.join();
        }
        end = System.currentTimeMillis();
        System.out.println("Sync: " + count1 + "   time: " + (end - start));
        //====================================
        start = System.currentTimeMillis();
        testLongAdder(threads);
        for (Thread tt : threads) {
            tt.start();
        }
        for (Thread tt : threads) {
            tt.join();
        }
        end = System.currentTimeMillis();
        System.out.println("longAdder: " + count3.longValue() + "   time: " + (end - start));

    }

}
